package com.cennavi.service.impl;

import com.cennavi.mapper.CommonMapper;
import com.cennavi.mapper.FormulaMapper;
import com.cennavi.mapper.RelationalMapper;
import com.cennavi.service.CommonService;
import com.cennavi.service.ScoreService;
import com.googlecode.aviator.AviatorEvaluator;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Created by lixiaoshuang on 2018/10/18.
 */
@Service
public class ScoreServiceImpl implements ScoreService {
    @Resource
    FormulaMapper formulaMapper;
    @Resource
    CommonMapper commonMapper;
    @Resource
    RelationalMapper relationalMapper;
    @Override
    public Object getScore(List<Map> list) {
        if(list==null || list.size()==0){
            return null;
        }
//        Map param=list.get(0);
        //最终结果
        Object object=null;
        for(Map param:list){
            //查询使用的公式
            List<Map> fmlist=formulaMapper.selectByStatasOrId("1", null);
            //结果 以每个公式的父id作为key，value 为左右子公式封装好的结果集list
            Map<String,List<Map>> result=new HashMap<String,List<Map>>();
            for(Map item:fmlist){
                //计算item公式需要的结果集
                Map<String,Object> itemMap=new HashMap<>();
                //公式数据来源的表
                String tablename=item.get("tablename").toString();
                if(tablename!=null && tablename.length()>0){
                    String[] tables=tablename.split(",");
                    for(String table:tables){
                        //每个表里面的列名
                        List temptable=new ArrayList<>();
                        temptable.add(table);
//                    List<String> columns=commonMapper.queryColumnsToShow(temptable);
                        //查询item里面所需要的数据
                        List<Map> data=commonMapper.queryData(temptable,param,param.get("type").toString(),param.get("casttype").toString(),item.get("sql")==null?null:item.get("sql").toString());
                        itemMap.putAll(data.get(0));
                    }
                }

                if(item.get("fid")!=null){
                    if(result.get(item.get("fid"))!=null){
                        List<Map> resultlist=result.get(item.get("fid"));
                        for(Map m:resultlist){
                            itemMap.putAll(m);
                        }
                    }

                }
                //查询公式中需要的变量的值
                List<Map> relationList=relationalMapper.selectDateByfmid(Integer.parseInt(item.get("id").toString()));
                for(Map i:relationList){
                    itemMap.put(i.get("name").toString(),i.get("value"));
                }
                //将入参加入
                itemMap.putAll(param);

                //加入上一级的计算结果

                List<Map> resultL=result.get(item.get("id").toString());
                if(resultL!=null){
                    for(Map m:resultL){
                        itemMap.putAll(m);
                    }
                }


                Pattern pattern = Pattern.compile("-?[0-9]+.?[0-9]+");

                for(String s:itemMap.keySet()){
                    String str=itemMap.get(s).toString();
                    //判断是否是数字
                    Matcher isNum = pattern.matcher(str);
                    if (isNum.matches()) {
                        itemMap.put(s,Double.parseDouble(str));
                    }
                }
                Object obj= AviatorEvaluator.execute(item.get("text").toString(),itemMap );
                Map itemreslut=new HashMap<>();
                itemreslut.put(item.get("name").toString(),obj);
                if(item.get("fid")!=null){
                    if(result.get(item.get("fid"))!=null){
                        List<Map> resultlist=result.get(item.get("fid"));
                        for(Map m:resultlist){
                            itemMap.putAll(m);
                        }
                    }else {
                        List<Map> resultlist=new ArrayList<Map>();
                        relationList.add(itemreslut);
                        result.put(item.get("fid").toString(),relationList);
                    }
                }else {
                   param.put("score",obj);
                }

            }
        }


        return list;
    }
}
